V nalogi se bomo igrali s slovarji, ki opisujejo, kje se nahaja kakšen kraj. Slovar je lahko recimo, tak
svet = {
"Evropa": {
"Slovenija": {
"Gorenjska": {
"Kranj": {},
"Radovljica": {},
"Zali log": {},
},
"Štajerska": {
"Maribor": {},
"Celje": {}
},
"Osrednja": {
"Ljubljana": {
"Vič": {
"FMF": {
"2.02": {
"tretja vrsta desno": {
"peti stol z desne": {
"Benjamin": {}
}
}
}
}
},
"Šiška": {}
}
}
},
"Nemčija": {
"Bavarska": {
"Munchen": {}
},
"Berlin": {}
},
},
"Amerika": {
"ZDA": {
"Teksas": {
"Houston": {},
"Austin": {}
},
"Kalifornija": {
"San Francisco": {}
},
"Anchorage": {}
},
"Kanada": {}
},
"Azija": {
"Osaka": {}
}
}
Ključi slovarja so torej nizi, vsebine pa so slovarji, ki so lahko tudi prazni. Namig: Oglejte si kako preveriti, ali je neka stuktura prazna,
Napiši funkcijo vrniVse(kraji)
, ki kot argument dobi slovar,
kakršen je gornji, in vrne po abecedi urejen seznam vseh krajev
in reči v njem.
def vrniVse(kraji): '''po abesedi urejen seznam vseh krajev in reči v slovarju ''' if not kraji : # če je slovar prazen return [] seznamVseh = [] for el in kraji: # dodamo ključ seznamVseh.append(el) # in vse elemente slovarja, ki je vrednost seznamVseh += vrniVse(kraji[el]) return sorted(seznamVseh)
Napiši funkcijo prestej(kraji)
, ki vrne število vseh krajev in
reči, ki se pojavijo v podanem slovarju.
def prestej(kraji): '''koliko je stvari v slovarju kraji''' # v praznem slovarju ni stvari if len(kraji) == 0: return 0 # pregledamo vse elemente slovarja in prištejemo 1 za ključ # in ustrezno število stvari v pripdajočem podslovarju koliko = 0 for slovar in kraji.values(): koliko += 1 # za ključ! kolikoVPodsl = prestej(slovar) koliko += kolikoVPodsl return koliko # načeloma je prvi stavek if odveč, zato lahko napišemo def prestejV2(kraji): '''koliko je stvari v slovarju kraji''' # pregledamo vse elemente slovarja in prištejemo 1 za ključ # in ustrezno število stvari v pripdajočem podslovarju koliko = 0 for slovar in kraji.values(): koliko += 1 # za ključ! kolikoVPodsl = prestejV2(slovar) koliko += kolikoVPodsl return koliko
Denimo, da imamo slovar (kot sta kraji
in svet
), ki kot vrednosti spet vsebuje
slovarje.
Sestavi funkcijo najSlovar(slovar)
, ki vrne tisti slovar,
ki vsebuje največ ključev.
def najSlovar(slovar) : ''' V slovarju slovarjev vrnemo slovar, ki vsebuje največ ključev ''' if not slovar : # če je slovar prazen return slovar #kandidat za največjega je kar ta slovar kanNajSlovar = slovar # morda se v kakšni vrednosti skriva večji slovar for kljuc in slovar: # pogledamo najSlovar v ustrezni vrednosti vrednost = slovar[kljuc] kandidat = najSlovar(vrednost) if len(kandidat) > len(kanNajSlovar) : # našli smo boljšega kanNajSlovar = kandidat return kanNajSlovar
Sestavi funkcijo jeVSlovarju(slovar, nekaj)
, ki ugotovi, ali je
v slovarju slovar
tudi niz nekaj
(bodisi kot ključ, bodisi kot vrednost)
def jeVSlovarju(slovar, nekaj) : ''' Ali je v slovarju slovar tudi niz nekaj (bodisi kot ključ, bodis kot vrednost)''' if not slovar : # če je slovar prazen return False # pregledamo vse ključe for kljuc in slovar: # pogledamo če je morda to ta ključ if kljuc == nekaj: return True # je morda v vrednosti, ki je slovar if jeVSlovarju(slovar[kljuc], nekaj): return True # nekaj ni bil ne ključ, en v kateri od vrenosti, torej je ni! return False
Sestavi funkcijo vrniVrednost(slovar, nekaj)
, ki vrne tisto vrednost
iz slovarja slovarjev slovar
, ki pripada ključu nekaj
Če pa v slovarju slovarjev nekaj
ni ključ, naj vrne None
def vrniVrednost(slovar, nekaj) : ''' Ali je v slovarju slovar tudi niz nekaj (bodisi kot ključ, bodis kot vrednost)''' if not slovar : # če je slovar prazen return None # pregledamo vse ključe for kljuc in slovar: # pogledamo če je morda to ta ključ if kljuc == nekaj: return slovar[kljuc] # je morda v vrednosti, ki je slovar kaj = vrniVrednost(slovar[kljuc], nekaj) if kaj != None : # torej je bilo return kaj # nekaj nismo našli v nobenem slovarju, torej je ni! return None
V nekem uspešnem podjetju ima skoraj vsak zaposleni svojega šefa. Seveda imajo tudi šefi svoje šefe in ti spet svoje šefe itn. Dobili smo podatke o hierarhiji v podjetju in ugotovili, da velja naslednje:
Napisali bomo nekaj funkcij, s katerimi bomo preučili razmere v podjetju.
Podatke smo dobili v obliki seznama parov oblike (uslužbenec, šef)
.
Vsi uslužbenci so predstavljeni z nizi (ki so običajno njihova imena oz.
priimki). Zgled:
[('Mojca', 'Tilen'), ('Andrej', 'Tilen'), ('Tilen', 'Zoran')]
Komentar: Tilen ima pod seboj dva podrejena (Andreja in Mojco), njegovi šef pa je Zoran. Zoran nima šefa, vsi ostali pa so njegovi podrejeni.
Napišite funkcijo slovarSefov(seznam)
, ki bo iz zgoraj opisanega
seznama zgradila slovar šefov. Ključi v seznamu naj bodo uslužbenci,
vrednosti pa njihovi šefi. Zgled:
>>> slovarSefov([('Mojca', 'Tilen'), ('Andrej', 'Tilen'), ('Tilen', 'Zoran')])
{'Andrej': 'Tilen', 'Mojca': 'Tilen', 'Tilen': 'Zoran'}
def slovarSefov(seznam): '''Glede na zgornji opis vrne slovar šefov''' slovar = {} for usluzbenec, sef in seznam: slovar[usluzbenec] = sef return slovar
Napišite funkcijo neposrednoPodrejeni(seznam)
, ki bo iz zgoraj opisanega
seznama sestavila slovar neposredno podrejenih. Vrednost pri vsakem
ključu naj bo množica tistih uslužbencev, ki imajo le-ta ključ za svojega
šefa. Zgled:
>>> neposrednoPodrejeni([('Mojca', 'Tilen'), ('Andrej', 'Tilen'), ('Tilen', 'Zoran')])
{'Zoran': {'Tilen'}, 'Tilen': {'Andrej', 'Mojca'}}
Zoranu je torej neposredno podrejen le Tilen, Tilnu pa sta podrejena tako Andrej kot Mojca.
def neposrednoPodrejeni(seznam): '''Glede na zgornji opis vrne slovar šef : množica neposredno podrejenih''' podrejeni = {} for usluzbenec, sef in seznam: # sprehodimo se po parih iz seznama if sef not in podrejeni: # če smo našli novega šefa podrejeni[sef] = set() # je potrebno narediti nov vnos v slovar podrejeni[sef].add(usluzbenec) return podrejeni
Sestavite funkcijo verigaNadrejenih(usluzbenec, slovar)
, ki kot prvi
argument dobi niz, ki predstavlja nekega uslužbenca, kot drugi argument
pa dobi slovar šefov (v obliki kot ga vrne funkcija slovarSefov
).
Funkcija naj sestavi seznam, ki po vrsti vsebuje: šefa osebe usluzbenec
,
šefa od njegovega šefa itn. (dokler končno ne pridemo do osebe, ki nima šefa).
Zgled:
>>> verigaNadrejenih('Mojca', {'Andrej': 'Tilen', 'Mojca': 'Tilen', 'Tilen': 'Zoran'})
['Tilen', 'Zoran']
Mojci je nadrejen Tilen, kateremu je nadrejen Zoran, torej sta Mojčina šefa Tilen in Zoran.
def verigaNadrejenih(usluzbenec, slovar): '''sestavi seznam, ki predstavlja verigo nadreejenih''' # če oseba nima šefa, je njegova veriga prazna # oseba nima šefa, če se ne pojavi kot ključ if usluzbenec not in slovar.keys(): return [] # uslužbenec ima šefa! sef = slovar[usluzbenec] seznamNadrejenih = [sef] # določimo verigo nadrejenih od šefa verNadrSef = verigaNadrejenih(sef, slovar) # združimo seznama seznamNadrejenih = seznamNadrejenih + verNadrSef return seznamNadrejenih def verigaNadrejenihV2(usluzbenec, slovar): '''Glede na zgornji opis vrne zaporedni seznam oseb, ki so uslužbencu nadrejeni''' '''brez rekurzije''' veriga = [] while usluzbenec in slovar: # če uslužbenec ima šefa (ko ga ne bo imel, smo na koncu verige!) usluzbenec = slovar[usluzbenec] # vzamemo njegovega šefa - v naslednjem koraku bomo vzeli njegovega šefa ... veriga.append(usluzbenec) # in ga dodamo return veriga
Sestavite funkcijo mnozicaPodrejenih(usluzbenec, slovar)
, ki kot prvi
argument dobi ime uslužbenca, kot drugi argument pa slovar neposredno
podrejenih (v obliki kot ga vrne funkcija neposrednoPodrejeni
). Funkcija
naj sestavi in vrne množico vseh tistih oseb, ki so (posredno ali
neposredno) podrejeni osebi usluzbenec
. Zgled:
>>> mnozicaPodrejenih('Zoran', {'Zoran': {'Tilen'}, 'Tilen': {'Andrej', 'Mojca'}, 'Mojca' : {'Urša'}})
{'Andrej', 'Mojca', 'Tilen', 'Urša'}
Zoranju je neposredno podrejen Tilen, torej sta mu podrejena tudi Tilnova podrejena Andrej in Mojca, ter Urša, ker je ta podrejena Mojci.
def mnozicaPodrejenih(usluzbenec, slovar): '''vrne _množico_ vseh tistih oseb, ki so (posredno ali neposredno) podrejeni osebi `usluzbenec`.''' # komentarjev NAMENOMA ni ! dodaj = [usluzbenec] podrejeni = set() while len(dodaj) > 0: u = dodaj[-1] del dodaj[-1] if u not in slovar: continue for v in slovar[u]: if v not in podrejeni: dodaj.append(v) podrejeni.add(v) return podrejeni
Tistemu uslužbencu, za katerega velja:
pravimo big boss. Sestavite funkcijo bigBoss(slovar)
, ki kot argument
dobi slovar nadrejenih in vrne ime osebe, ki je big boss v podjetju oz.
vrednost None
, če to podjetje nima big boss-a. Zgled:
>>> bigBoss({'Andrej': 'Tilen', 'Mojca': 'Tilen', 'Tilen': 'Zoran'})
'Zoran'
def bigBoss(slovar): '''nekdo, ki nima šefa in je šef vsem ostalim''' if len(slovar) == 0: return None # tak slovar ga nima! bigBoss = list(slovar.keys())[0] # kandidat za velikega šefa (če ne bo imel nadrejenih!) nadrejeni = verigaNadrejenih(bigBoss, slovar) # kdo so kandidatu nadrejeni? if len(nadrejeni) > 0: # če je prejšnji kandidat imel nadrejene bigBoss = nadrejeni[-1] # je samo zadnji kandidat za velikega šefa # dobili smo kandidata za big boss-a for uslužbenec in slovar: # pregledamo vse uslužbence if uslužbenec == bigBoss: # kandidata spustimo continue nadrejeni = verigaNadrejenih(uslužbenec, slovar) # pogledamo vse uslužbencu nadrejene if (len(nadrejeni) == 0) or (nadrejeni[-1] != bigBoss): # če jih ni, potem bigBNoss ni nadrejeni temu, torej ni veliki šef! return None # ali pa najvišji nadrejeni temu uslužbencu ni bil naš veliki šef - v firmi velikega šefa ni return bigBoss
Ker ste v komentarjih napisali, da je ukvarjanje s permutacijami vaša najbolj priljubbljena tema, se permutacije vračajo v vsem svojem sijaju!
V slovarju imamo shranjeno permutacijo naravnih števil od {1: 3, 2: 2, 3: 1}
.
Pri vseh nalogah predpostavite, da je število x zagotovo element permutacije. Prav tako tudi to, da je permutacija pravilna.
Le za ogrevanje (naloga "ne šteje") rešite naslednjo nalogo:
Sestavite funkcijo slika(permutacija, x)
, vrne pa sliko števila x
s podano permutacijo.
def slika(permutacija, x): return permutacija[x]
Sestavite funkcijo jePermutacija(slovar)
, ki vrne True
, če dan
slovar predstavlja permutacijo, in False
sicer.
Npr. slovar {1: 3, 3: 1}
ni permutacija, saj ne vemo, kam se slika 2. Tudi {1: 3, 2: 2, 3: 2, 4: 1}
ni slovar, saj 4 ni slika nobenega števila!
def jePermutacija(slovar): # Za vsa števila od 1 do n bomo pogledali, če nastopajo tako v domeni # kot v sliki permutacije. Imeli bomo seznam je_v_domeni, ki ima na # mestu i - 1 zapisano, če smo ugotovili, da i je v domeni permutacije. # Podobno storimo za sliko. n = len(slovar) je_v_domeni = [False for i in range(n)] je_v_sliki = [False for i in range(n)] # Nato gremo čez vse ključe k in pripadajoče vrednosti v v slovarju. # Če sta tako k kot v med 1 in n, označimo, da sta v domeni in sliki, # sicer pa vemo, da slovar ne predstavlja permutacije. for k, v in slovar.items(): if 1 <= k <= n and 1 <= v <= n: je_v_domeni[k - 1] = True je_v_sliki[v - 1] = True else: return False # Na koncu pogledamo, ali so v domeni in sliki nastopala vsa števila. # Funkcija all vrne True natanko takrat, ko so vsi elementi v seznamu # enaki True. return all(je_v_domeni) and all(je_v_sliki)
Sestavite funkcijo slike(permutacija, x, n)
, ki vrne zaporedje slik,
ki ga dobimo, če začnemo s številom x
in na njem n
-krat uporabimo
permutacijo permutacija
.
>>> slike({1: 3, 2: 4, 3: 2, 4: 1}, 1, 2)
[1, 3, 2]
def slike(permutacija, x, n): # Funkcijo definiramo rekurzivno. Če je n > 0, naredimo sliko y, nato # pa dodamo še seznam n - 1 slik elementa y. if n == 0: return [x] else: y = permutacija[x] ostale = slike(permutacija, y, n - 1) return [x] + ostale def slike_nerekurzivno(permutacija, x, n): r=[] for i in range(n+1): r.append(x) x = permutacija[x] return r
Sestavite funkcijo cikel(permutacija, x)
, ki vrne celoten cikel, ki
se začne s številom x
.
>>> cikel({1: 3, 2: 2, 3: 1}, 1)
[1, 3]
>>> cikel({1: 3, 2: 2, 3: 1}, 2)
[2]
def cikel(permutacija, x): # Dokler slika zadnjega elementa, ki smo ga dodali v cikel, ni enaka # začetnemu elementu y, dodamo sliko ter ponavljamo. cikel = [x] y = permutacija[x] while y != x: cikel.append(y) y = permutacija[y] return cikel
Sestavite funkcijo cikli(permutacija)
, ki vrne seznam disjunktnih
ciklov dane permutacije. Vsak cikel naj se začne z najmanjšim številom
v ciklu, cikli pa naj bodo urejeni po začetnem številu.
>>> cikli({1: 3, 2: 2, 3: 1})
[[1, 3], [2]]
def cikli(permutacija): # V seznam izracunaniCikli si shranjujemo do sedaj izračunane cikle, v seznam # ugotovljena pa vsa tista števila, za katera smo že ugotovili, kateremu # ciklu pripadajo. izracunaniCikli = [] ugotovljena = [] # Nato gremo zaporedoma čez vsa števila od 1 do n. Če za neko število # še nismo ugotovili, kam spada, je najmanjše v svojem ciklu. Zato # izračunamo njegov cikel, ga dodamo k ciklom, vsa števila iz cikla pa # dodamo med ugotovljena. for i in range(1, len(permutacija) + 1): if i not in ugotovljena: c = cikel(permutacija, i) izracunaniCikli.append(c) ugotovljena.extend(c) return izracunaniCikli
Socialno omrežje zaljubljenosti podamo s slovarjem, ki ime osebe preslika v množico vseh, v katere je oseba zaljubljena (ena oseba je lahko zaljubljena v več oseb). Na primer, slovar
s = {'Ana' : {'Bine','Cene'},
'Bine' : set(),
'Cene' : {'Bine'},
'Davorka' : {'Davorka'},
'Eva' : {'Bine'}}
nam pove, da je Ana zaljubljena v Bineta in Cenete, Bine ni zaljubljen, Cene ljubi Bineta, Davorka samo sebe in Eva Bineta.
Opomba*: Naloga je podobna nalogi"Ljubezen nam je vsem v pogubo", le da so tukaj ljubljene osebe v množici in ne v seznamu. Prav tako moramo vračati množice!_
Sestavite funkcijo narcisoidi(d)
, ki sprejme slovar zaljubljenih
in vrne monžico tistih, ki ljubijo same sebe.
def narcisoidi(d): return {oseba for oseba in d if oseba in d[oseba]}
Sestavite funkcijo ljubljeni(d)
, ki sprejme slovar zaljubljenih
in vrne množico tistih, ki so ljubljeni.
def ljubljeni(d): return {ljubljen for oseba in d for ljubljen in d[oseba]}
Sestavite funkcijo pari(d)
, ki sprejme slovar zaljubljenih
in vrne množico vseh parov, ki so srečno ljubljeni. Vsak
par naj se pojavi samo enkrat in sicer tako, da je sta zaljubljenca
našteta po abecedi. Na primer, če sta Ana in Bine zaljubljena,
dodamo par ('Ana','Bine')
.
def pari(d): return {tuple(sorted((x, y))) for x in d for y in d[x] if x in d[y]}
Sestavite funkcijo ustrezljivi(oseba, d)
, ki sprejme ime osebe ter
slovar zaljubljenih, vrne pa množico vseh ljudi, ki so do dane osebe
še posebej ustrežljivi. Posebej ustrežljivi so seveda za to, ker so
bodisi zaljubljeni v dano osebo, bodisi so zaljubljeni v osebo, ki je
posebej ustrežljiva do nje, in tako naprej.
Na primer, če imamo slovar
s = {'Ana' : {'Bine', 'Cene'},
'Bine' : {'Ana'},
'Cene' : {'Bine'},
'Davorka' : {'Davorka'},
'Eva' : {'Bine'}}
so do Ceneta posebej ustrežljivi Ana (ki je zaljubljena vanj), Bine (ki je zaljubljen v Ano), Eva (ki je zaljubljena v Bineta), ter seveda Cene, ki je zaljubljen v Evo.
def ustrezljivi(oseba, d): # seznam, v katerega nabiramo ustrežljive osebe ustrezljivi = set() # najprej dodamo tiste, ki ljubijo prvo osebo dodani = {o for o in d if oseba in d[o]} # dokler smo koga dodali, dodajamo ustrežljive while dodani: ustrezljivi.update(dodani) # sedaj pa dodajamo tiste, ki ljubijo nazadnje dodane osebe dodani = {o for o in d for dodan in dodani if dodan in d[o] and o not in ustrezljivi} return ustrezljivi
V neki datoteki, ki ima lahko več vrstic, so zapisana imena. Znotraj posamične vrstice so imena ločena z vejicami (brez presledkov). Primer take datoteke:
Jaka,Peter,Miha,Peter,Anja
Franci,Roman,Renata,Jožefa
Pavle,Tadeja,Arif,Filip,Gašper
Sestavite funkcijo kolikokrat_se_pojavi(niz, ime)
, ki vrne število
pojavitev imena ime
v nizu imen niz
.
>>> kolikokrat_se_pojavi('Alojz,Samo,Peter,Alojz,Franci', 'Alojz')
2
def kolikokrat_se_pojavi(niz, ime): return niz.split(',').count(ime) # Alternativna rešitev (brez uporabe metode count) def kolikokrat_se_pojavi_alt(niz, ime): vsa_imena = niz.split(',') stevec = 0 for s in vsa_imena: if s == ime: stevec += 1 return stevec
Sestavite funkcijo koliko(niz, datoteka)
, ki na izhodno datoteko z
imenom datoteka
za vsako ime zapiše, kolikokrat se pojavi v nizu niz
.
Na primer, če je niz enak 'Jaka,Luka,Ante,Luka'
, naj funkcija v izhodno
datoteko zapiše
Jaka 1
Luka 2
Ante 1
Pozor: Imena naj bodo izpisana v takem vrstnem redu, kakor si sledijo
njihove prve pojavitve v nizu niz
.
def koliko(niz, datoteka): imena = niz.split(',') brez_ponovitev = [] for ime in imena: if ime not in brez_ponovitev: brez_ponovitev.append(ime) with open(datoteka, 'w', encoding='utf-8') as f: for ime in brez_ponovitev: print(ime, imena.count(ime), file=f) # Alternativna rešitev def koliko_alt(niz, datoteka): imena = [] stevci = [] for ime in niz.split(','): if ime not in imena: imena.append(ime) stevci.append(1) else: stevci[imena.index(ime)] += 1 with open(datoteka, 'w', encoding='utf-8') as f: for ime, stevec in zip(imena, stevci): print(ime, stevec, file=f) # Še ena možna rešitev (z uporabo slovarja) def koliko_alt2(niz, datoteka): imena = niz.split(',') stevec = {} for ime in imena: stevec[ime] = stevec.get(ime, 0) + 1 with open(datoteka, 'w', encoding='utf-8') as f: for ime in imena: if ime not in stevec: continue print(ime, stevec[ime], file=f) del stevec[ime]
Sestavite funkcijo koliko_iz_datoteke(vhodna, izhodna)
, ki naj naredi
isto kot funkcija koliko
, le da podatke prebere iz datoteke. Torej, na
izhodno datoteko z imenom izhodna
naj za vsako ime zapiše, kolikokrat
se pojavi v datoteki z imenom vhodna
.
Pozor: Vhodna datoteka ima lahko več vrstic. Imena izpišite v enakem
vrstnem redu, kot si sledijo njihove prve pojavitve v datoteki vhodna
.
def koliko_iz_datoteke(vhodna, izhodna): vrstice = [] # Seznam vseh vrstic v datoteki vhodna. with open(vhodna, encoding='utf-8') as f: for vrstica in f: vrstice.append(vrstica.strip()) # Odstranimo '\n' s konca vrstice. imena = ','.join(vrstice) # Niz z vsemi imeni iz datoteke. koliko(imena, izhodna)
Sestavite funkcijo koliko_urejen(vhodna, izhodna)
, ki na izhodno
datoteko z imenom izhodna
za vsako ime zapiše, kolikokrat se pojavi v
datoteki z imenom vhodna
. Imena naj bodo urejena padajoče po frekvenci
pojavitev. Imena, ki imajo enako frekvenco, naj bodo nadalje urejena
leksikografsko (tj. po abecednem vrstnem redu).
Primer: Če je na datoteki imena_vhod.txt vsebina
Luka,Jaka
Luka,Miha,Miha
Miha,Aleš,Aleš
naj bo po klicu funkcije koliko_urejen('imena_vhod.txt', 'imena_izhod.txt')
na datoteki imena_izhod.txt naslednja vsebina:
Miha 3
Aleš 2
Luka 2
Jaka 1
def koliko_urejen(vhod, izhod): imena = [] # Seznam vseh imen. brez_ponovitev = [] # Seznam imen brez ponovitev. with open(vhod, encoding='utf-8') as f: for vrstica in f: for ime in vrstica.strip().split(','): imena.append(ime) if ime not in brez_ponovitev: brez_ponovitev.append(ime) # Seznam pari bo vseboval pare oblike (-3, 'Miha'). Druga komponenta bo # ime; prva komponenta bo število pojavitev tega imena, pomnoženo z -1. pari = [] for ime in brez_ponovitev: pari.append((-imena.count(ime), ime)) # Metoda sort uredi števila naraščajoče po vrednosti, nize pa leksikografsko # (tj. tako kot so urejeni v leksikonu). Pare uredi glede na prvo komponento, # tiste z enako prvo komponento pa še glede na drugo komponento. pari.sort() with open(izhod, 'w', encoding='utf-8') as f: for s, ime in pari: print(ime, -s, file=f) # Alternativna rešitev (uporablja izpeljane sezname, množice in lambda funkcije) def koliko_urejen_alt(vhod, izhod): with open(vhod, encoding='utf-8') as f: imena = ','.join([vrstica.strip() for vrstica in f]) enkrat_imena = set(imena.split(',')) pari = [(ime, kolikokrat_se_pojavi(imena, ime)) for ime in enkrat_imena] pari.sort(key=lambda p: (-p[1], p[0])) with open(izhod, 'w', encoding='utf-8') as f: for ime, s in pari: print(ime, s, file=f)
Vsako LEGO kocko lahko opišemo z dvema lastnostima: tipom (torej obliko) in barvo.
Če boste nalogo uspešno rešili še pred koncem, si lahko ogledate
seznam vseh možnih barv
kock, pri tej nalogi pa bomo predpostavili le tri barve: rdečo, modro
in rumeno. Tipov LEGO kock pa je ogromno,
zato jih bomo predstavili kar z nizi kot na primer '2x2'
, '4x1-tanka'
ali pa 'nogice'
. Sprejmimo dogovor, da nobeno ime tipa ne vsebuje pike.
Vsebino škatle podamo s seznamom vseh kock, ki so v njej. Vsaka kocka
je opisana z nizom, ki vsebuje tip kocke in barvo, ki sta ločeni s piko.
Npr. kocka tipa '2x2'
rdeče barve je predstavljena z nizom '2x2.rdeča'
.
Napišite funkcijo slovar_kock(skatla)
, ki dobi seznam skatla
in sestavi
slovar vsebovanih kock, urejen po tipih ter po barvah, kot prikazuje primer:
>>> slovar_kock(['2x2.rdeča', '2x2.rdeča', 'nogice.modra', '2x2.modra'])
{'nogice': {'modra': 1}, '2x2': {'rdeča': 2, 'modra': 1}}
def slovar_kock(skatla): '''Vrne slovar lego kock''' sk = dict() for kocka in skatla: tip, barva = kocka.split('.') if tip not in sk: sk[tip] = dict() sk[tip][barva] = sk[tip].get(barva, 0) + 1 return sk
Napišite funkcijo lahko_sestavimo(skatla, model)
, ki dobi dva slovarja
kock, in vrne True
natanko tedaj, ko je možno modelček (za katerega
potrebujemo kocke, ki so podane s slovarjem model
) sestaviti s kockami,
ki so v škatli.
>>> model = {'4x1': {'modra': 1}, '2x2': {'rdeča': 2, 'modra': 1}}
>>> skatla = {'4x1': {'modra': 3, 'rdeča': 2}, '2x2': {'rdeča': 4, 'modra': 1, 'rumena': 5}}
>>> lahko_sestavimo(skatla, model)
True
>>> model_2 = {'4x1': {'rumena': 1}, '2x2': {'rdeča': 1, 'rumena': 2}}
>>> lahko_sestavimo(skatla, model_2)
False
def lahko_sestavimo(skatla, model): '''Ali lahko sestavimo model, če imamo na voljo škatlo kock skatla''' for tip, barve in model.items(): for barva, cnt in barve.items(): if cnt > skatla.get(tip, {}).get(barva, 0): return False return True
Napišite funkcijo hitro_sestavljanje(skatla, model)
, ki vrne True
,
če je možno modelček sestaviti “na hitro”, torej tako, da barve niso
pomembne (še vedno pa je pomembno, da uporabimo kocke ustreznega tipa).
>>> model = {'4x1': {'modra': 2}, '2x2': {'rdeča': 2, 'modra': 1}}
>>> skatla_1 = {'4x1': {'rdeča': 3}, '2x2': {'rdeča': 1, 'rumena': 5}}
>>> skatla_2 = {'4x1': {'rumena': 3, 'rdeča': 2}, '2x2': {'rumena': 1, 'rdeča': 1}}
>>> hitro_sestavljanje(skatla_1, model)
True
>>> hitro_sestavljanje(skatla_2, model)
False
def hitro_sestavljanje(skatla, model): '''Ali lahko "na hitro"(brez upoštevanja barv) sestavimo model iz kock v škatli skatla ''' for tip, barve in model.items(): if sum(barve.values()) > sum(skatla.get(tip, {}).values()): return False return True